package com.tdk.mybatisplus.demo.common.advice;


import com.tdk.mybatisplus.demo.common.entity.Function2Param;
import com.tdk.mybatisplus.demo.common.entity.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * Controller层切面
 * </p>
 *
 * @author: taodingkai
 * @modified:
 * @since: 2022/08/08 9:58
 */
@RestControllerAdvice
@Slf4j
@ResponseBody
public class DefaultControllerAdvice implements ResponseBodyAdvice<Object> {

    public static final Map<String, Function2Param<String,String,Boolean>>NON_STANDARD_URL_MAP=new HashMap<String,Function2Param<String,String,Boolean>>(){{
        put("swagger-resources",(p1,p2)->p1.contains(p2));
        put("api-docs",(p1,p2)->p1.contains(p2));
        put("/",(p1,p2)->p1.equals(p2));
    }};
    
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return Boolean.TRUE;
    }

    /**
     * <p>
     * 统一结果处理
     * </p>
     *
     * @param body
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return java.lang.Object
     * @author: taodingkai
     * @since: 2022/08/08 18:08
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (Objects.isNull(body)) {
            //null
            return Result.success(body);
        } else if (isInNonStandardUrlSet(request.getURI().getPath())) {
            //swagger
            return body;
        } else if (body instanceof Result) {
            //Result对象不用处理
            return body;
        } else {
            // 直接包裹一层
            return Result.success(body);
        }
    }
    
    /**
     * <p>
     * 统一处理白名单
     * </p>
     *
     *
     * @param url
     * @return java.lang.Boolean
     * @author: taodingkai
     * @since: 2022/8/18 11:53 
     */
    public Boolean isInNonStandardUrlSet(String url){
        Boolean isInNonStandardUrlSet =Boolean.FALSE;
        for (Map.Entry<String, Function2Param<String, String, Boolean>> entry:NON_STANDARD_URL_MAP.entrySet()) {
            if(entry.getValue().apply(url, entry.getKey())){
                isInNonStandardUrlSet=Boolean.TRUE;
            }
        }
        return isInNonStandardUrlSet;
    }
}
